﻿/************************************************************************************
* Copyright (c) 2019 All Rights Reserved.
*命名空间：Separate.BLL
*文件名： SeparateAuto
*创建人： Liebeskind
*创建时间：2019/6/12 16:50:41
*描述
*=====================================================================
*修改标记
*修改时间：2019/6/12 16:50:41
*修改人：Liebeskind
*描述：
************************************************************************************/
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Commonality.Model;
using Commonality.Model.Tray;
using Commonality.Model.PLCControl;
using Commonality.Model.ScanningGunModel;
using Commonality.DAL.WZS_SFCS;
using Commonality.DAL.MySQL;
using Separate.Model;
using Separate.Model.Vision;
using Separate.Model.EmptyTrayGather;
using System.Windows.Forms;
using System.Threading;
using HalconDotNet;
using Commonality.Model.Classify;
using Separate.Model.ClassEngine;
using Separate.BLL.InfoForm;

namespace Separate.BLL
{
    public static class SeparateAutoMain
    {
        public static bool ThisClose;
        public static Separate.BLL.VisionWindow visionWindowA;
        public static Separate.BLL.VisionWindow visionWindowB;
        public static InfoForm.NgInfoForm ngInfoForm;
        public static void SeparateStart()
        {
            ThisClose = false;
            SFCSInterface.SFCSInterfaceInit();
            //SFCSDataDispose.SFCSDataDisposeInit();
            PLC.PLCInit(AutoMainLoop);
            SG.SGInit();
            EmptyTray.EmptyTrayInit();
            Classify.ClassifyInit();
        }
        public static void SeparateStop()
        {
            PLC.PLCClose();            
        }
        public static void AutoMainLoop()
        {
            AutoFunction.EntranceSG();
            AutoFunction.EntranceQRCodeDispose();

            AutoFunction.Buff2Sepa();

            AutoFunction.VisionDetection();

            AutoFunction.SeparateSG();
            AutoFunction.SeparateQRCodeDispose();


            AutoFunction.ThisOff();
        }
    }
    public static class AutoFunction
    {
        /// <summary>
        /// 入料口扫码触发方法
        /// </summary>
        public static void EntranceSG()
        {
            //A
            if (CPLCControl.LAD_GetDblCell(PLC.dEntrance_SQRC_A) == 1 && !SG.EntranceSGA_Flag)
            {
                SG.EntranceSGACRCode = "";
                SG.EntranceSGA.ScanCodeTimeout(SG.Timeout);
                SG.EntranceSGA_Flag = true;
                Log4Net.MsgInfo("A侧入料Buff扫码");
            }
            //B
            if (CPLCControl.LAD_GetDblCell(PLC.dEntrance_SQRC_B) == 1 && !SG.EntranceSGB_Flag)
            {
                SG.EntranceSGBCRCode = "";
                SG.EntranceSGB.ScanCodeTimeout(SG.Timeout);
                SG.EntranceSGB_Flag = true;
                Log4Net.MsgInfo("B侧入料Buff扫码");
            }
        }
        /// <summary>
        /// 入料口扫码结果分类处理
        /// </summary>
        public static void EntranceQRCodeDispose()
        {
            //A
            if (SG.EntranceSGA_Flag)
            {

                #region 有效扫码-主线
                if (SG.EntranceSGACRCode.Length == SG.EffeLength)
                {
                    
                    bool perm = false;
                    string message = "";
                    ProductCellData ProductCell = new ProductCellData() { usn = "", usnInfo = new string[20], bin = new string[10] };
                    SFCSDataDispose.SFCSControl_Admittance(ref SG.EntranceSGACRCode,ref perm,ref message,ref ProductCell);

                    //
                    if (perm)
                    {
                        SFCSDataDispose.ProductCellData_Model(ProductCell, ref EmptyTray.AEmptyTrayModel_BUFF);
                        Parameter.writeAEmptyTrayModel_BUFF(ref EmptyTray.AEmptyTrayModel_BUFF);
                        //准入
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_A, 2);
                        Log4Net.MsgInfo("产品准入");
                        Log4Net.MsgInfo("产品类型:" + EmptyTray.AEmptyTrayModel_BUFF.ToString());
                        //非对象，特别的：这里正常摞，还得经过分盘进入线体，还未生成线体内的对象，所以不能新增对象（不记录数据）
                        //AutoForm.autoForm.buffDisA(System.Drawing.Color.Lime, SG.EntranceSGACRCode, ProductCell.usnInfo[3]);
                    }
                    else
                    {
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_A, 3);
                        Log4Net.MsgInfo("错误站点:" + message + "\r\n" + "异常摞:写入数据库");
                        //作为对象：异常摞进入线体，新增一个异常对象（记录数据）
                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.EntranceSGACRCode, 1, "站点异常:显示站点为" + message);
                    }

                    SG.EntranceSGACRCode_ErrTime = 0;
                    SG.EntranceSGACRCode = "";
                    SG.EntranceSGA_Flag = false;
                }
                #endregion
                #region 扫码超时
                else if (SG.EntranceSGACRCode != "")
                {
                    if (SG.EntranceSGACRCode_ErrTime == 0)
                    {
                        Log4Net.MsgInfo("A侧入料扫码超时");
                        SeparateAutoMain.ngInfoForm.NgLogDis("A侧入料扫码超时");
                        //CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_A, PLC.ScalarAbnormal);
                        //TODO:扫码超时处理
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_A, 4);    //避免入料方向错误，发送4通知PLC旋转摞
                        Log4Net.MsgInfo("入料方向错误，通知PLC旋转入料");
                        SG.EntranceSGACRCode_ErrTime = 1;
                        SG.EntranceSGACRCode = "";
                    }
                    else if (SG.EntranceSGACRCode_ErrTime == 1)
                    {
                        Log4Net.MsgInfo("A侧无法识别二维码");
                        //TODO:无法扫码处理
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_A, 3);    //整摞通行
                        Log4Net.MsgInfo("");
                        SG.EntranceSGACRCode_ErrTime = 0;
                        SG.EntranceSGACRCode = "";
                    }
                    SG.EntranceSGA_Flag = false;
                }
                #endregion

            }

            //B
            if (SG.EntranceSGB_Flag)
            {

                #region 有效扫码-主线
                if (SG.EntranceSGBCRCode.Length == SG.EffeLength)
                {

                    bool perm = false;
                    string message = "";
                    ProductCellData ProductCell = new ProductCellData() { usn = "", usnInfo = new string[20], bin = new string[10] };
                    SFCSDataDispose.SFCSControl_Admittance(ref SG.EntranceSGBCRCode, ref perm, ref message, ref ProductCell);
                    //
                    if (perm)
                    {
                        SFCSDataDispose.ProductCellData_Model(ProductCell, ref EmptyTray.BEmptyTrayModel_BUFF);
                        Parameter.writeBEmptyTrayModel_BUFF(ref EmptyTray.BEmptyTrayModel_BUFF);
                        //准入
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_B, 2);
                        Log4Net.MsgInfo("产品准入");
                        Log4Net.MsgInfo("产品类型:" + EmptyTray.BEmptyTrayModel_BUFF.ToString());
                        //非对象，特别的：这里正常摞，还得经过分盘进入线体，还未生成线体内的对象，所以不能新增对象（不记录数据）
                        //AutoForm.autoForm.buffDisB(System.Drawing.Color.Lime, SG.EntranceSGBCRCode, ProductCell.usnInfo[3]);
                    }
                    else
                    {
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_B, 3);
                        Log4Net.MsgInfo("错误站点:" + message + "\r\n" + "异常摞:写入数据库");
                        //作为对象：异常摞进入线体，新增一个异常对象（记录数据）
                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.EntranceSGBCRCode, 1, "站点异常:显示站点为" + message);
                    }
                    SG.EntranceSGBCRCode_ErrTime = 0;
                    SG.EntranceSGBCRCode = "";
                    SG.EntranceSGB_Flag = false;
                }
                #endregion
                #region 扫码超时
                else if (SG.EntranceSGBCRCode != "")
                {
                    if (SG.EntranceSGBCRCode_ErrTime == 0)
                    {
                        Log4Net.MsgInfo("B侧入料扫码超时");
                        //CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_A, PLC.ScalarAbnormal);
                        //TODO:扫码超时处理
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_B, 4);    //避免入料方向错误，发送4通知PLC旋转摞
                        Log4Net.MsgInfo("入料方向错误，通知PLC旋转入料");
                        SG.EntranceSGBCRCode_ErrTime = 1;
                        SG.EntranceSGBCRCode = "";
                    }
                    else if (SG.EntranceSGBCRCode_ErrTime == 1)
                    {
                        Log4Net.MsgInfo("B侧无法识别二维码");
                        //TODO:无法扫码处理
                        CPLCControl.LAD_SetDblCell(PLC.dEntrance_SQRC_B, 3);    //整摞通行
                        Log4Net.MsgInfo("");
                        SG.EntranceSGBCRCode_ErrTime = 0;
                        SG.EntranceSGBCRCode = "";
                    }
                    SG.EntranceSGB_Flag = false;
                }
                #endregion

            }
        }
        /// <summary>
        /// 
        /// </summary>
        public static void Buff2Sepa()
        {
            if (CPLCControl.LAD_CheckCell(PLC.mBuff2Sepa_A) == 1)
            {
                //BUFF转移分盘
                Log4Net.MsgInfo("缓存转移" + EmptyTray.AEmptyTrayModel.ToString() + "->" + EmptyTray.AEmptyTrayModel_BUFF.ToString());
                EmptyTray.AEmptyTrayModel = EmptyTray.AEmptyTrayModel_BUFF;
                Parameter.writeAEmptyTrayModel(ref EmptyTray.AEmptyTrayModel);
                CPLCControl.LAD_ResetCell(PLC.mBuff2Sepa_A);
            }
            if (CPLCControl.LAD_CheckCell(PLC.mBuff2Sepa_B) == 1)
            {
                //BUFF转移分盘
                Log4Net.MsgInfo("缓存转移" + EmptyTray.BEmptyTrayModel.ToString() + "->" + EmptyTray.BEmptyTrayModel_BUFF.ToString());
                EmptyTray.BEmptyTrayModel = EmptyTray.BEmptyTrayModel_BUFF;
                Parameter.writeBEmptyTrayModel(ref EmptyTray.BEmptyTrayModel);
                CPLCControl.LAD_ResetCell(PLC.mBuff2Sepa_B);
            }
        }

        /// <summary>
        /// 分盘视觉处理
        /// </summary>
        public static void VisionDetection()
        {
            //TODO:分盘视觉处理：结果1.有产品且产品正常；2.有产品但产品异常；3.无产品视为封盖
            //A
            if (CPLCControl.LAD_CheckCell(PLC.mTakeImage_A) == 1)
            {
                #region 视觉处理并记录处理结果-缓存-主线

                CPLCControl.LAD_ResetCell(PLC.mTakeImage_A);
                string vision =  SeparateAutoMain.visionWindowA.Detection();
                if (vision == "异物")
                {
                    Log4Net.MsgInfo("A图像处理-异物");
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_A, 0);
                }
                else if (vision == "膜")
                {
                    Log4Net.MsgInfo("A图像处理-失膜");
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_A, 0);
                }
                else if (vision == "NG")
                {
                    Log4Net.MsgInfo("A图像处理异常");
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_A, 0);
                }
                else
                {
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_A, 1);
                    Log4Net.MsgInfo("A图像处理" + "OK");
                }
                #endregion
            }

            //TODO:分盘视觉处理：结果1.有产品且产品正常；2.有产品但产品异常；3.无产品视为封盖
            //B
            if (CPLCControl.LAD_CheckCell(PLC.mTakeImage_B) == 1)
            {
                #region 视觉处理并记录处理结果-缓存-主线

                CPLCControl.LAD_ResetCell(PLC.mTakeImage_B);
                string vision = SeparateAutoMain.visionWindowB.Detection();
                if (vision == "异物")
                {
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_B, 0);
                    Log4Net.MsgInfo("B图像处理-异物");
                }
                else if (vision == "膜")
                {
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_B, 0);
                    Log4Net.MsgInfo("B图像处理-失膜");
                }
                else if (vision == "NG")
                {
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_B, 0);
                    Log4Net.MsgInfo("B图像处理异常");
                }
                else
                {
                    CPLCControl.LAD_SetDblCell(PLC.dVisionResult2PLC_B, 1);
                    Log4Net.MsgInfo("B图像处理" + "OK");
                }
                #endregion
            }
        }

        /// <summary>
        /// 分盘扫码
        /// </summary>
        public static void SeparateSG()
        {
            //A
            if (CPLCControl.LAD_GetDblCell(PLC.dSeparate_SQRC_A) == 7 && !SG.AloneSGA1RCode_Flag && !SG.AloneSGA2RCode_Flag)          //plc->7:触发扫码
            {
                SG.AloneSGA1RCode = "";
                SG.AloneSGA2RCode = "";
                CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_A, 100);
                SG.AloneSGA1.ScanCodeTimeout(SG.Timeout);
                SG.AloneSGA2.ScanCodeTimeout(SG.Timeout);
                SG.AloneSGA1RCode_Flag = true;
                SG.AloneSGA2RCode_Flag = true;
                Vision.OldAVisionResult = Vision.MidAVisionResult;
                Log4Net.MsgInfo("A侧分盘扫码");
            }

            //B
            if (CPLCControl.LAD_GetDblCell(PLC.dSeparate_SQRC_B) == 7 && !SG.AloneSGB1RCode_Flag && !SG.AloneSGB2RCode_Flag)          //plc->7:触发扫码
            {
                SG.AloneSGB1RCode = "";
                SG.AloneSGB2RCode = "";
                CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_B, 100);
                SG.AloneSGB1.ScanCodeTimeout(SG.Timeout);
                SG.AloneSGB2.ScanCodeTimeout(SG.Timeout);
                SG.AloneSGB1RCode_Flag = true;
                SG.AloneSGB2RCode_Flag = true;
                Vision.OldBVisionResult = Vision.MidBVisionResult;
                Log4Net.MsgInfo("B侧分盘扫码");
            }
        }
        /// <summary>
        /// 分盘扫码结果分类处理
        /// </summary>
        public static void SeparateQRCodeDispose()
        {
            //A
            if (SG.AloneSGA1RCode_Flag&& SG.AloneSGA2RCode_Flag)
            {
                #region 有效扫码-主线
                if (SG.AloneSGA1RCode.Length == SG.EffeLength && SG.AloneSGA2RCode.Length == SG.EffeLength)
                {
                    EmptyTray.NewAEmptyTrayInfo = 0;        //非空tray
                    CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_A, 0);        //非空tray发送0
                    MySqlFunction.PacketData_P.Packet_Data_Delete_P("'" + SG.AloneSGA1RCode + "'");
                    MySqlFunction.PacketData_P.Packet_Data_Delete_P("'" + SG.AloneSGA2RCode + "'");


                    if (CPLCControl.LAD_GetDblCell(PLC.dVisionResult2Mysql_A) == 1)
                    {
                        //视觉检测Ok

                        if ((CPLCControl.LAD_GetDblCell(PLC.dHeight_A1) == 1 || CPLCControl.LAD_GetDblCell(PLC.dHeight_A2) == 1) && false)
                        {
                            //叠料
                            MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "叠料");
                            Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + "叠料");
                            SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + "叠料");
                            //AutoForm.autoForm.singleDisA(System.Drawing.Color.Blue, SG.AloneSGA1RCode, "叠料");
                        }
                        else
                        {
                            string[] str = new string[2] { "", "" };
                            try
                            {
                                bool Cons = false;          //对比结果
                                string mess = "";
                                ProductCellData Cell_1 = new ProductCellData() { usn = "", usnInfo = new string[20], bin = new string[10] };
                                ProductCellData Cell_2 = new ProductCellData() { usn = "", usnInfo = new string[20], bin = new string[10] };
                                str = SFCSDataDispose.SFCSControl_Consistency(ref SG.AloneSGA1RCode, ref SG.AloneSGA2RCode, ref Cons, ref mess, ref Cell_1, ref Cell_2);
                                MySqlFunction.TrayCellDataList.TrayCellDataList_INSERT(Cell_1, Cell_2);//TODO:datalist数据源

                                if (Cell_1.usnInfo[6] != "PO" || Cell_2.usnInfo[6] != "PO")
                                {
                                    Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + Cell_1.usnInfo[6] + "\r\n" + SG.AloneSGA1RCode + Cell_1.usnInfo[6] + "\r\n" + "站点错误");
                                    SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + Cell_1.usnInfo[6] + "\r\n" + SG.AloneSGA1RCode + Cell_1.usnInfo[6] + "\r\n" + "站点错误");
                                    MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "站点错误");                          //匹配出差-更新流向表
                                }
                                else if (Cell_1.usnInfo[7] != "NO" || Cell_2.usnInfo[7] != "NO")
                                {
                                    Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + Cell_1.usnInfo[7] + "\r\n" + SG.AloneSGA1RCode + Cell_1.usnInfo[7] + "\r\n" + "产品被Hold");
                                    SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + Cell_1.usnInfo[7] + "\r\n" + SG.AloneSGA1RCode + Cell_1.usnInfo[7] + "\r\n" + "产品被Hold");
                                    MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "产品被Hold");                          //匹配出差-更新流向表
                                }
                                else if (Cell_1.usnInfo[11] != "OUT" || Cell_2.usnInfo[11] != "OUT")
                                {
                                    Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + Cell_1.usnInfo[11] + "\r\n" + SG.AloneSGA1RCode + Cell_1.usnInfo[11] + "\r\n" + "非OUT");
                                    SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + Cell_1.usnInfo[11] + "\r\n" + SG.AloneSGA1RCode + Cell_1.usnInfo[11] + "\r\n" + "非OUT");
                                    MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "非OUT");                          //匹配出差-更新流向表
                                }
                                else
                                {
                                    if (!Cons)
                                    {
                                        //Tray内不一致
                                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "产品不匹配:");                          //匹配出差-更新流向表
                                        Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + "-List:" +
                                                                                     Cell_1.usnInfo[0]  + "/" +
                                                                                     Cell_1.usnInfo[3]  + "/" +
                                                                                     Cell_1.usnInfo[4]  + "/" +
                                                                                     Cell_1.usnInfo[10] + "/");
                                        Log4Net.MsgTcpInfo(SG.AloneSGA2RCode + "-List:" +
                                                                                     Cell_2.usnInfo[0]  + "/" +
                                                                                     Cell_2.usnInfo[3]  + "/" +
                                                                                     Cell_2.usnInfo[4]  + "/" +
                                                                                     Cell_2.usnInfo[10] + "/");

                                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + "不匹配:" +
                                                                                     Cell_1.usnInfo[0]  + "    " +
                                                                                     Cell_1.usnInfo[3]  + "    " +
                                                                                     Cell_1.usnInfo[4]  + "    " +
                                                                                     Cell_1.usnInfo[10] + "    ");
                                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA2RCode + "不匹配:" +
                                                                                     Cell_2.usnInfo[0]  + "    " +
                                                                                     Cell_2.usnInfo[3]  + "    " +
                                                                                     Cell_2.usnInfo[4]  + "    " +
                                                                                     Cell_2.usnInfo[10] + "    ");
                                    }
                                    else
                                    {

                                        Discern(Cell_1, Cell_2);        //特征识别

                                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 0, "OK");
                                        //AutoForm.autoForm.singleDisA(System.Drawing.Color.Lime, SG.AloneSGA1RCode, "准入");
                                        Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + "\r\n" + SG.AloneSGA1RCode + "\r\n" + "准入");
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "返回参数错误:" + str[0] + str[1]);                          //匹配出差-更新流向表 
                                Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + str[0] + "\r\n" + SG.AloneSGA1RCode + str[1] + "\r\n" + "SFCS异常");
                                SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + str[0] + "\r\n" + SG.AloneSGA1RCode + str[1] + "\r\n" + "SFCS异常");
                                Log4Net.MsgTcpInfo(e.ToString());
                            }
                        }
                    }
                    else
                    {
                        //视觉检测异常
                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "产品异物");
                        //AutoForm.autoForm.singleDisA(System.Drawing.Color.Blue, SG.AloneSGA1RCode, "异物");
                        Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + "\r\n" + SG.AloneSGA1RCode + "\r\n" + "产品异物");
                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + "\r\n" + SG.AloneSGA1RCode + "\r\n" + "产品异物");
                    }



                    SG.AloneSGA1RCode = "";
                    SG.AloneSGA1RCode_Flag = false;
                    SG.AloneSGA2RCode = "";
                    SG.AloneSGA2RCode_Flag = false;
                    Log4Net.MsgInfo("分盘扫码完成-进入分类区");
                }
                #endregion
                #region 半空盘
                else if ((SG.AloneSGA1RCode != "" && SG.AloneSGA1RCode.Length != SG.EffeLength && SG.AloneSGA2RCode.Length == SG.EffeLength)|| 
                         (SG.AloneSGA2RCode != "" && SG.AloneSGA2RCode.Length != SG.EffeLength && SG.AloneSGA1RCode.Length == SG.EffeLength))
                {
                    EmptyTray.NewAEmptyTrayInfo = 0;        //半空tray
                    CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_A, 0);        //半空tray发送0
                    if (SG.AloneSGA1RCode.Length == SG.EffeLength)
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGA1RCode, 1, "半空盘");
                        Log4Net.MsgTcpInfo(SG.AloneSGA1RCode + "半空盘");
                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA1RCode + "半空盘");
                    }
                    else
                    {
                        Log4Net.MsgTcpInfo(SG.AloneSGA2RCode + "半空盘");
                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGA2RCode + "半空盘");
                    }
                    SG.AloneSGA1RCode = "";
                    SG.AloneSGA1RCode_Flag = false;
                    SG.AloneSGA2RCode = "";
                    SG.AloneSGA2RCode_Flag = false;
                }
                #endregion
                #region 码异常
                else if (SG.AloneSGA1RCode != "" && SG.AloneSGA2RCode != "" &&
                            SG.AloneSGA1RCode.Length != SG.EffeLength && SG.AloneSGA2RCode.Length != SG.EffeLength)
                {
                    //空盘
                    //确认为空tray
                    //搜索此Model空Tray对应仓位,并记录进缓存（空Tray收集取料位到位触发，发送给收集设备）
                    EmptyTray.NewAEmptyTrayInfo = EmptyTrayClass.EmptyTrayToStorehouse(EmptyTray.AEmptyTrayModel);
                    if (EmptyTray.AEmptyTrayModel == TrayModel.Unknown) { Log4Net.MsgInfo("不能识别的Model,请及时更新TrayModel集合"); };
                    CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_A, EmptyTray.NewAEmptyTrayInfo);        //是空tray发送空tray类型映射仓号、
                    Log4Net.MsgInfo("空tray映射" + EmptyTray.NewAEmptyTrayInfo);
                    //AutoForm.autoForm.singleDisA(System.Drawing.Color.Lime, SG.AloneSGA1RCode, "空TRAY");
                    SG.AloneSGA1RCode = "";
                    SG.AloneSGA1RCode_Flag = false;
                    SG.AloneSGA2RCode = "";
                    SG.AloneSGA2RCode_Flag = false;
                }
                #endregion

            }


            //B
            if (SG.AloneSGB1RCode_Flag && SG.AloneSGB2RCode_Flag)
            {
                #region 有效扫码-主线
                if (SG.AloneSGB1RCode.Length == SG.EffeLength && SG.AloneSGB2RCode.Length == SG.EffeLength)
                {
                    EmptyTray.NewBEmptyTrayInfo = 0;        //非空tray
                    CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_B, 0);        //非空tray发送0
                    MySqlFunction.PacketData_P.Packet_Data_Delete_P("'" + SG.AloneSGB1RCode + "'");
                    MySqlFunction.PacketData_P.Packet_Data_Delete_P("'" + SG.AloneSGB2RCode + "'");


                    if (CPLCControl.LAD_GetDblCell(PLC.dVisionResult2Mysql_B) == 1)
                    {
                        //视觉检测Ok

                        if ((CPLCControl.LAD_GetDblCell(PLC.dHeight_B1) == 1 || CPLCControl.LAD_GetDblCell(PLC.dHeight_B2) == 1) && false)
                        {
                            //叠料
                            MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "叠料");
                            Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + "叠料");
                            SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + "叠料");
                            //ButoForm.autoForm.singleDisB(System.Drawing.Color.Blue, SG.BloneSGB1RCode, "叠料");
                        }
                        else
                        {
                            string[] str = new string[2] { "", "" };
                            try
                            {
                                bool Cons = false;          //对比结果
                                string mess = "";
                                ProductCellData Cell_1 = new ProductCellData() { usn = "", usnInfo = new string[20], bin = new string[10] };
                                ProductCellData Cell_2 = new ProductCellData() { usn = "", usnInfo = new string[20], bin = new string[10] };
                                str = SFCSDataDispose.SFCSControl_Consistency(ref SG.AloneSGB1RCode, ref SG.AloneSGB2RCode, ref Cons, ref mess, ref Cell_1, ref Cell_2);
                                MySqlFunction.TrayCellDataList.TrayCellDataList_INSERT(Cell_1, Cell_2);//TODO:datalist数据源

                                if (Cell_1.usnInfo[6] != "PO" || Cell_2.usnInfo[6] != "PO")
                                {
                                    Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + Cell_1.usnInfo[6] + "\r\n" + SG.AloneSGB1RCode + Cell_1.usnInfo[6] + "\r\n" + "站点错误");
                                    SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + Cell_1.usnInfo[6] + "\r\n" + SG.AloneSGB1RCode + Cell_1.usnInfo[6] + "\r\n" + "站点错误");
                                    MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "站点错误");                          //匹配出差-更新流向表
                                }
                                else if (Cell_1.usnInfo[7] != "NO" || Cell_2.usnInfo[7] != "NO")
                                {
                                    Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + Cell_1.usnInfo[7] + "\r\n" + SG.AloneSGB1RCode + Cell_1.usnInfo[7] + "\r\n" + "产品被Hold");
                                    SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + Cell_1.usnInfo[7] + "\r\n" + SG.AloneSGB1RCode + Cell_1.usnInfo[7] + "\r\n" + "产品被Hold");
                                    MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "产品被Hold");                          //匹配出差-更新流向表
                                }
                                else if (Cell_1.usnInfo[11] != "OUT" || Cell_2.usnInfo[11] != "OUT")
                                {
                                    Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + Cell_1.usnInfo[11] + "\r\n" + SG.AloneSGB1RCode + Cell_1.usnInfo[11] + "\r\n" + "非OUT");
                                    SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + Cell_1.usnInfo[11] + "\r\n" + SG.AloneSGB1RCode + Cell_1.usnInfo[11] + "\r\n" + "非OUT");
                                    MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "非OUT");                          //匹配出差-更新流向表
                                }
                                else
                                {
                                    if (!Cons)
                                    {
                                        //Tray内不一致
                                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "产品不匹配:");                          //匹配出差-更新流向表
                                        Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + "-List:" +
                                                                                     Cell_1.usnInfo[0] + "/" +
                                                                                     Cell_1.usnInfo[3] + "/" +
                                                                                     Cell_1.usnInfo[4] + "/" +
                                                                                     Cell_1.usnInfo[10] + "/");
                                        Log4Net.MsgTcpInfo(SG.AloneSGB2RCode + "-List:" +
                                                                                     Cell_2.usnInfo[0] + "/" +
                                                                                     Cell_2.usnInfo[3] + "/" +
                                                                                     Cell_2.usnInfo[4] + "/" +
                                                                                     Cell_2.usnInfo[10] + "/");

                                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + "不匹配:" +
                                                                                     Cell_1.usnInfo[0] + "    " +
                                                                                     Cell_1.usnInfo[3] + "    " +
                                                                                     Cell_1.usnInfo[4] + "    " +
                                                                                     Cell_1.usnInfo[10] + "    ");
                                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB2RCode + "不匹配:" +
                                                                                     Cell_2.usnInfo[0] + "    " +
                                                                                     Cell_2.usnInfo[3] + "    " +
                                                                                     Cell_2.usnInfo[4] + "    " +
                                                                                     Cell_2.usnInfo[10] + "    ");
                                    }
                                    else
                                    {

                                        Discern(Cell_1, Cell_2);        //特征识别

                                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 0, "OK");
                                        //ButoForm.autoForm.singleDisB(System.Drawing.Color.Lime, SG.BloneSGB1RCode, "准入");
                                        Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + "\r\n" + SG.AloneSGB1RCode + "\r\n" + "准入");
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "返回参数错误:" + str[0] + str[1]);                          //匹配出差-更新流向表 
                                Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + str[0] + "\r\n" + SG.AloneSGB1RCode + str[1] + "\r\n" + "SFCS异常");
                                SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + str[0] + "\r\n" + SG.AloneSGB1RCode + str[1] + "\r\n" + "SFCS异常");
                                Log4Net.MsgTcpInfo(e.ToString());
                            }
                        }
                    }
                    else
                    {
                        //视觉检测异常
                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "产品异物");
                        //ButoForm.autoForm.singleDisB(System.Drawing.Color.Blue, SG.BloneSGB1RCode, "异物");
                        Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + "\r\n" + SG.AloneSGB1RCode + "\r\n" + "产品异物");
                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + "\r\n" + SG.AloneSGB1RCode + "\r\n" + "产品异物");
                    }



                    SG.AloneSGB1RCode = "";
                    SG.AloneSGB1RCode_Flag = false;
                    SG.AloneSGB2RCode = "";
                    SG.AloneSGB2RCode_Flag = false;
                    Log4Net.MsgInfo("分盘扫码完成-进入分类区");
                }
                #endregion
                #region 半空盘
                else if ((SG.AloneSGB1RCode != "" && SG.AloneSGB1RCode.Length != SG.EffeLength && SG.AloneSGB2RCode.Length == SG.EffeLength) ||
                         (SG.AloneSGB2RCode != "" && SG.AloneSGB2RCode.Length != SG.EffeLength && SG.AloneSGB1RCode.Length == SG.EffeLength))
                {
                    EmptyTray.NewBEmptyTrayInfo = 0;        //半空tray
                    CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_B, 0);        //半空tray发送0
                    if (SG.AloneSGB1RCode.Length == SG.EffeLength)
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_INSERT(SG.AloneSGB1RCode, 1, "半空盘");
                        Log4Net.MsgTcpInfo(SG.AloneSGB1RCode + "半空盘");
                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB1RCode + "半空盘");
                    }
                    else
                    {
                        Log4Net.MsgTcpInfo(SG.AloneSGB2RCode + "半空盘");
                        SeparateAutoMain.ngInfoForm.NgLogDis(SG.AloneSGB2RCode + "半空盘");
                    }
                    SG.AloneSGB1RCode = "";
                    SG.AloneSGB1RCode_Flag = false;
                    SG.AloneSGB2RCode = "";
                    SG.AloneSGB2RCode_Flag = false;
                }
                #endregion
                #region 码异常
                else if (SG.AloneSGB1RCode != "" && SG.AloneSGB2RCode != "" && 
                        SG.AloneSGB1RCode.Length != SG.EffeLength && SG.AloneSGB2RCode.Length != SG.EffeLength)
                {
                    //空盘
                    //确认为空tray
                    //搜索此Model空Tray对应仓位,并记录进缓存（空Tray收集取料位到位触发，发送给收集设备）
                    EmptyTray.NewBEmptyTrayInfo = EmptyTrayClass.EmptyTrayToStorehouse(EmptyTray.BEmptyTrayModel);
                    if (EmptyTray.BEmptyTrayModel == TrayModel.Unknown) Log4Net.MsgInfo("不能识别的Model,请及时更新TrayModel集合");
                    CPLCControl.LAD_SetDblCell(PLC.dSeparate_SQRC_B, EmptyTray.NewBEmptyTrayInfo);        //是空tray发送空tray类型映射仓号、
                    Log4Net.MsgInfo("空tray映射" + EmptyTray.NewBEmptyTrayInfo);
                    //AutoForm.autoForm.singleDisB(System.Drawing.Color.Lime, SG.AloneSGB1RCode, "空TRBY");
                    SG.AloneSGB1RCode = "";
                    SG.AloneSGB1RCode_Flag = false;
                    SG.AloneSGB2RCode = "";
                    SG.AloneSGB2RCode_Flag = false;
                }
                #endregion

            }

        }
        /// <summary>
        /// 特征识别方法
        /// </summary>
        /// <param name="cell"></param>
       public static void Discern(ProductCellData cell1, ProductCellData cell2)
        {
            ClassModel classModel = new ClassModel();
            byte PnType = Classify.classifyEngine.NewEigenvectorExtract(cell1, ref classModel);                       //从陌生实例的datalist中提取特征，进行识别和认证，或构造新类
            string Eigenvector = classModel.StringEigenvector;
            MySqlFunction.TrayCellDataList.TrayCellDataList_Eigenvector_UPDATE(cell1.usn, cell2.usn, ref Eigenvector);   //记录此盘的特征/SN索引特征
            Log4Net.MsgInfo("识别特征：" + Eigenvector);

            if (PnType == 1)
            {
                Classify.classifyPnSave(cell1.usnInfo[0], cell1.usnInfo[1], cell1.usnInfo[2], cell1.usnInfo[8]);
                Log4Net.MsgInfo("识别特征：" + "新PN(新类型)" + cell1.usnInfo[0]);
            }
            else
            {
                Log4Net.MsgInfo("识别特征：" + "旧PN(旧类型)" + cell1.usnInfo[0]);               
            }
        }


        #region 关机处理
        public static void ThisOff()
        {
            while (SeparateAutoMain.ThisClose)
            {
                Thread.Sleep(100);
            }
        }
        #endregion
    }
    public static class SG
    {
        
        public static double Timeout = 2400;
        public static CKeyenceScanningGunModel EntranceSGA;
        public static CKeyenceScanningGunModel EntranceSGB;

        public static CKeyenceScanningGunModel AloneSGA1;
        public static CKeyenceScanningGunModel AloneSGB1;
        public static CKeyenceScanningGunModel AloneSGA2;
        public static CKeyenceScanningGunModel AloneSGB2;

        public static CKeyenceScanningGunModel ClassifyExit_SG;
        public static CKeyenceScanningGunModel BackflowExit_SG;


        public static bool EntranceSGA_Flag;
        public static bool EntranceSGB_Flag;


        public static int EffeLength;
        public static string EntranceSGACRCode = "";
        
        public static string EntranceSGBCRCode = "";


        public static string AloneSGA1RCode = "";
        public static bool AloneSGA1RCode_Flag = false;
        public static string AloneSGB1RCode = "";
        public static bool AloneSGB1RCode_Flag = false;
        public static string AloneSGA2RCode = "";
        public static bool AloneSGA2RCode_Flag = false;
        public static string AloneSGB2RCode = "";
        public static bool AloneSGB2RCode_Flag = false;


        public static string ClassifyExitQRcode = "";
        public static string BackflowExitQRcode = "";


        #region 标志
        /// <summary>
        /// 入口扫码异常（全空盘/方向反）次数
        /// </summary>
        public static short EntranceSGACRCode_ErrTime;
        /// <summary>
        /// 入口扫码异常（全空盘/方向反）次数
        /// </summary>
        public static short EntranceSGBCRCode_ErrTime;
        #endregion

        public static void SGInit()
        {
            EntranceSGA = new CKeyenceScanningGunModel("COM12", 115200, 8, Parity.None, StopBits.One, EntranceSGA_QRcode);
            EntranceSGB = new CKeyenceScanningGunModel("COM11", 115200, 8, Parity.None, StopBits.One, EntranceSGB_QRcode);
            AloneSGA1 = new CKeyenceScanningGunModel("COM4", 115200, 8, Parity.None, StopBits.One, AloneSGA1_QRcode);
            AloneSGB1 = new CKeyenceScanningGunModel("COM2", 115200, 8, Parity.None, StopBits.One, AloneSGB1_QRcode);
            AloneSGA2 = new CKeyenceScanningGunModel("COM8", 115200, 8, Parity.None, StopBits.One, AloneSGA2_QRcode);
            AloneSGB2 = new CKeyenceScanningGunModel("COM6", 115200, 8, Parity.None, StopBits.One, AloneSGB2_QRcode);

            Timeout = 2400;

            EffeLength = ("ABCDEFGHIJKLMNOPR\r\n").Length;

            EntranceSGACRCode_ErrTime = 0;
            EntranceSGBCRCode_ErrTime = 0;

            AloneSGA1RCode_Flag = false;
            AloneSGB1RCode_Flag = false;
            AloneSGA2RCode_Flag = false;
            AloneSGB2RCode_Flag = false;
            EntranceSGA_Flag = false;
            EntranceSGB_Flag = false;
        }

        public static void EntranceSGA_QRcode(ref string code)
        {
            EntranceSGACRCode = code;
            Log4Net.MsgInfo("A入料口扫码：\r\n" + code);
        }
        public static void EntranceSGB_QRcode(ref string code)
        {
            EntranceSGBCRCode = code;
            Log4Net.MsgInfo("B入料口扫码：\r\n" + code);
        }
        public static void AloneSGA1_QRcode(ref string code)
        {
            AloneSGA1RCode = code;
            Log4Net.MsgInfo("A1分盘扫码：\r\n" + code);
        }

        public static void AloneSGB1_QRcode(ref string code)
        {
            AloneSGB1RCode = code;
            Log4Net.MsgInfo("B1分盘扫码：\r\n" + code);
        }
        public static void AloneSGA2_QRcode(ref string code)
        {
            AloneSGA2RCode = code;
            Log4Net.MsgInfo("A1分盘扫码：\r\n" + code);
        }

        public static void AloneSGB2_QRcode(ref string code)
        {
            AloneSGB2RCode = code;
            Log4Net.MsgInfo("B1分盘扫码：\r\n" + code);
        }
        public static void ClassifyExit_QRcode(ref string code)
        {
            ClassifyExitQRcode = code;
            Log4Net.MsgInfo("分类区出口扫码：\r\n" + code);
            Log4Net.MsgInfo("\r\n");
        }
        public static void BackflowExit_QRcode(ref string code)
        {
            BackflowExitQRcode = code;
            Log4Net.MsgInfo("回流线出口扫码：\r\n" + code);
            Log4Net.MsgInfo("\r\n");
        }
    }
    static class Vision
    {
        #region 分盘过程中的视觉结果传递
        /// <summary>
        /// 前视觉结果
        /// </summary>
        public static VisionResult OldAVisionResult = VisionResult.Vacancy;
        /// <summary>
        /// 前视觉结果
        /// </summary>
        public static VisionResult OldBVisionResult = VisionResult.Vacancy;

        /// <summary>
        /// 中视觉结果
        /// 
        /// </summary>
        public static VisionResult MidAVisionResult = VisionResult.Vacancy;
        /// <summary>
        /// 中视觉结果
        /// </summary>
        public static VisionResult MidBVisionResult = VisionResult.Vacancy;

        /// <summary>
        /// 后视觉结果
        /// </summary>
        public static VisionResult NewAVisionResult = VisionResult.Vacancy;
        /// <summary>
        /// 后当前视觉结果
        /// </summary>
        public static VisionResult NewBVisionResult = VisionResult.Vacancy;
        #endregion

    }
    public static class EmptyTray
    {
        public static void EmptyTrayInit()
        {
            AEmptyTrayModel_BUFF = TrayModel.NULL;
            BEmptyTrayModel_BUFF = TrayModel.NULL;
            AEmptyTrayModel = TrayModel.NULL;
            BEmptyTrayModel = TrayModel.NULL;

            Parameter.EmptyTrayLoad();
        }
        
        /// <summary>
        /// A侧空tray类型标志缓存记录
        /// </summary>
        public static TrayModel AEmptyTrayModel_BUFF = TrayModel.NULL;
        /// <summary>
        /// B侧空tray类型标志缓存记录
        /// </summary>
        public static TrayModel BEmptyTrayModel_BUFF = TrayModel.NULL;

        /// <summary>
        /// A侧空tray类型标志
        /// </summary>
        public static TrayModel AEmptyTrayModel = TrayModel.NULL;
        /// <summary>
        /// B侧空tray类型标志
        /// </summary>
        public static TrayModel BEmptyTrayModel = TrayModel.NULL;

        /// <summary>
        /// 空tray目标
        /// 0：非空tray
        /// 1-6:前往对应目标
        /// 7:无对应仓位-报警
        /// </summary>
        public static short NewAEmptyTrayInfo = 0;
        /// <summary>
        /// 空tray目标
        /// 0：非空tray
        /// 1-6:前往对应目标
        /// </summary>
        public static short NewBEmptyTrayInfo = 0;

    }
    public static class ExcludeList
    {
        /// <summary>
        /// 人工设置禁止进入自动线线别
        /// </summary>
        public struct ExcludeLine
        {
            public static byte TB1_1FT_1;
            public static byte TB1_1FT_2;
            public static byte TB1_1FT_3;
            public static byte TB1_1FT_4;
            public static byte TB1_1FT_5;
            public static byte TB1_1FT_6;
            public static byte TB1_1FT_7;
            public static byte TB1_1FT_8;
            public static byte TB1_1FT_9;
            public static byte TB1_1FT_10;
            public static byte TB1_1FT_11;
            public static byte TB1_1FT_12;
            public static byte TB1_1FT_13;
            public static byte TB1_1FT_14;
            public static byte TB1_1FT_15;
            public static byte TB1_1FT_16;
        }

        /// <summary>
        /// 人工设置禁止进入自动线料号
        /// </summary>
        public static List<string> ExcludePn;
    }

    public static class Classify
    {
        public static ClassifyEngine classifyEngine;

        public static void ClassifyInit()
        {
            classifyEngine = new ClassifyEngine();

            List<string> OldPnList = new List<string>();
            ClassifyPnData.PNListDataLoad(ref OldPnList);    //加载待分类的PN
            foreach (var item in OldPnList)
            {
                string pni = item;
                ClassifyPnAdd(ref pni);
            }
        }

        /// <summary>
        /// 扩充PN值域/记录PN/MO/投入时间/计划产量
        /// </summary>
        /// <param name="pn"></param>
        /// <param name="mo"></param>
        /// <param name="pro"></param>
        /// <param name="bir"></param>
        public static void classifyPnSave(string pn, string mo, string pro, string bir)
        {
            MySqlFunction.AttentionPnData.AttentionPnData_INSERT(pn, mo, pro, bir);
            Log4Net.MsgInfo("扩充PN");
        }

        private static void ClassifyPnAdd(ref string pn)
        {
            ClassModel classModel = new ClassModel();
            ProductCellData productCellData = new ProductCellData() { usn = "", usnInfo = new string[11] { pn, "", "", "", "ANSI", "TB1-1FT-09", "", "", "", "", "3" }, bin = new string[1] { "" } };
            Classify.classifyEngine.NewEigenvectorExtract(productCellData, ref classModel);
            Log4Net.MsgInfo("加载类型：" + classModel.StringEigenvector);
        }
    }


}
